package gateway.mgt.runtime

import com.amihaiemil.camel.Yaml
import gateway.mgt.api.ApiDefinition
import gateway.mgt.api.ApiGroup
import groovy.transform.ToString
import utils.ConfigHelper
import utils.GitHelper

@ToString(includePackage = false, includes = ["name"])
class GatewayCore {

    String name
    String description

    Boolean autoDeploy = false
    Boolean deployed

    static hasMany = [apiGroups: ApiGroup, services: String, registrations: String, runtimes: RuntimeMetrics]
    //services, ApplicationContext ID List or Service ID list,  formatter:  $spring.application.name:$server.port  , e.g. 'GATEWAY-CORE:8765' or 'GATEWAY-CORE:**' or 'GATEWAY-CORE'
    //more see: https://cloud.spring.io/spring-cloud-static/Finchley.RELEASE/multi/multi__addressing_an_instance.html

    Date dateCreated
    Date lastUpdated

    static constraints = {
        name(blank: true, unique: true)
        apiGroups()
        autoDeploy(nullable: false)
        deployed(nullable: false, bindable: false)
        services()
        registrations()
        runtimes()
        dateCreated()
        lastUpdated()
        description(nullable: true, widget: 'textarea')
    }

    def beforeValidate() {
        if (!name) {
            name = apiGroups.collect { it.name }.join("+")
        }

        deployed = !services?.isEmpty()
    }

    String toYamlString() {
        final groupBuildElements = [routes: Yaml.createYamlSequenceBuilder(), hystrix: Yaml.createYamlMappingBuilder()]

        ApiGroup.findAllByCore(this).each { apiGroup ->
            ApiDefinition.findAllByApiGroup(apiGroup).each { ApiDefinition apiDef ->
                apiDef.route(groupBuildElements)
            }
        }

        Yaml.createYamlMappingBuilder()
                .add("spring",
                Yaml.createYamlMappingBuilder()
                        .add("cloud",
                        Yaml.createYamlMappingBuilder()
                                .add("gateway",
                                Yaml.createYamlMappingBuilder()
                                        .add("routes", groupBuildElements.routes.build())
                                        .build()
                        ).build()
                ).build())
                .add("hystrix",
                Yaml.createYamlMappingBuilder()
                        .add("command", groupBuildElements.hystrix.build()
                ).build()
        ).build().toString()
    }

    Map<String, Object> publish() {
        //auto detect deploy
        if (autoDeploy && !deployed) {
            deployed = ManagedContainer.choose().deploy(name)
        }
        //commit and push git repo
        def result = GitHelper.cover("${name}.yml", toYamlString()) as Map
        //publish refresh event
        result.refresh = ConfigHelper.refresh(services)
        return result
    }
}
